//
//  CDVGetBeaconLocate.m
//  post
//
//  Created by jing zhao on 9/24/14.
//  Copyright (c) 2014 jing zhao. All rights reserved.
//
#define KEYARRAY   @"arrayBeacon"
#import "CDVGetBeaconLocate.h"

@interface CDVGetBeaconLocate ()

@property (strong, nonatomic)CLLocationManager *locationManager;
@property (strong, nonatomic)CDVInvokedUrlCommand* command;
@property (strong, nonatomic)NSArray *beacons;
@property (strong, nonatomic)NSMutableDictionary *beacons_cache;
@property (assign, nonatomic)BOOL listening;

@end


@implementation CDVGetBeaconLocate

- (NSDictionary *) beaconInputDataByBeacon:(CLBeacon *)beacon {
    for (NSDictionary *beaconInput in self.beacons) {
        if ([[beaconInput objectForKey:@"proximityUUID"] isEqualToString:[beacon.proximityUUID UUIDString]]
            && [[beaconInput objectForKey:@"major"] isEqualToString:[beacon.major stringValue]]
            && [[beaconInput objectForKey:@"minor"] isEqualToString:[beacon.minor stringValue]]) {
            return beaconInput;
        }
    }
    
    return nil;
}

- (void) setCache:(CLBeacon *)beacon byOn:(BOOL)on {
    NSDictionary *beaconInputData = [self beaconInputDataByBeacon:beacon];
    [self.beacons_cache setObject:[NSNumber numberWithBool:on] forKey:beaconInputData];
}

- (BOOL) getCache:(CLBeacon *)beacon {
    NSDictionary *beaconInputData = [self beaconInputDataByBeacon:beacon];
    return [[self.beacons_cache objectForKey:beaconInputData] boolValue];
}

- (void) onAllBeacons {
    for (NSDictionary *beaconInputData in self.beacons) {
        [self.beacons_cache setObject:[NSNumber numberWithBool:YES]
                               forKey:beaconInputData];
    }
}

- (void) pluginInitialize {
    self.listening = NO;
    self.beacons_cache = [NSMutableDictionary dictionaryWithCapacity:10];
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(localNotificationReceived:)
                                                 name:@"CDVLocalNotification"
                                               object:nil];
    
    if (!self.locationManager)
    {
        _locationManager = [[CLLocationManager alloc] init];
        self.locationManager.delegate = self;
    }
}

- (void) localNotificationReceived:(NSNotification *)notification {
    UILocalNotification *localNotification = notification.object;
    
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        NSDictionary *beaconInputData = [[localNotification.userInfo objectForKey:@"beaconInputData"] copy];
        
        CDVPluginResult*  pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:beaconInputData];
        [pluginResult setKeepCallbackAsBool:YES];
        
        
        [self.commandDelegate sendPluginResult:pluginResult
                                    callbackId:self.command.callbackId];
    });
    
    [[UIApplication sharedApplication] cancelLocalNotification:localNotification];
}

- (void)startMonitorBeaconLocate:(CDVInvokedUrlCommand*)command
{
    CDVPluginResult* pluginResult = nil;
    if (![CLLocationManager isMonitoringAvailableForClass:[CLBeaconRegion class]] ) {
        pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"Please enable location in Setting."];
        [self.commandDelegate sendPluginResult:pluginResult
                                    callbackId:command.callbackId];
        return;
    }
    
    if ([[UIApplication sharedApplication]backgroundRefreshStatus]!=UIBackgroundRefreshStatusAvailable) {
        pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"Please enable app background in Setting."];
        [self.commandDelegate sendPluginResult:pluginResult
                                    callbackId:command.callbackId];
    }
    
    if (self.listening) {
        // 停止
        
        //remove monitor
        for (int i =0; i<[self.beacons count];i++) {
            NSDictionary *dic = [self.beacons objectAtIndex:i];
            NSString * strUuid = [dic objectForKey:KEYPROXIMITYUUID];
            NSString * strMajor = [dic objectForKey:KEYMAJOR];
            NSString * strMinor = [dic objectForKey:KEYMINOR];
            NSString *strIndentify = [NSString stringWithFormat:@"%@%@%@", strUuid, strMajor, strMinor];
            
            NSUUID *uuid = [[NSUUID alloc]initWithUUIDString:strUuid];
            CLBeaconMajorValue majorValue = [strMajor intValue];
            CLBeaconMinorValue minorValue = [strMinor intValue];
            
            
            CLBeaconRegion *beaconRegion;
            
            beaconRegion  = [[CLBeaconRegion alloc]initWithProximityUUID:uuid major:majorValue minor:minorValue identifier:strIndentify];
            beaconRegion.notifyEntryStateOnDisplay = YES;
            beaconRegion.notifyOnEntry = YES;
            beaconRegion.notifyOnExit = YES;
            
            // 停止进入和进出
            [self.locationManager stopMonitoringForRegion:beaconRegion];
            [self.locationManager stopRangingBeaconsInRegion:beaconRegion];
        }
        
        [self.beacons_cache removeAllObjects];
    }
    
    //add monitor
    NSArray *arrayBeacons = [command.arguments objectAtIndex:0];
    for (int i =0; i<[arrayBeacons count];i++) {
        NSDictionary *dic = [arrayBeacons objectAtIndex:i];
        NSString * strUuid = [dic objectForKey:KEYPROXIMITYUUID];
        NSString * strMajor = [dic objectForKey:KEYMAJOR];
        NSString * strMinor = [dic objectForKey:KEYMINOR];
        NSString *strIndentify = [NSString stringWithFormat:@"%@%@%@", strUuid, strMajor, strMinor];
        
        NSUUID *uuid = [[NSUUID alloc]initWithUUIDString:strUuid];
        CLBeaconMajorValue majorValue = [strMajor intValue];
        CLBeaconMinorValue minorValue = [strMinor intValue];
        
        
        CLBeaconRegion *beaconRegion;
        
        beaconRegion  = [[CLBeaconRegion alloc]initWithProximityUUID:uuid major:majorValue minor:minorValue identifier:strIndentify];
        beaconRegion.notifyEntryStateOnDisplay = YES;
        beaconRegion.notifyOnEntry = YES;
        beaconRegion.notifyOnExit = YES;
        
        // 监听进入和进出
        [self.locationManager startMonitoringForRegion:beaconRegion];
        [self.locationManager startRangingBeaconsInRegion:beaconRegion];
    }
    self.beacons = arrayBeacons;
    
    // 初始化所有的Beacon开关
    for (NSDictionary *beacon in self.beacons) {
        [self.beacons_cache setObject:[NSNumber numberWithBool:YES]
                               forKey:beacon];
    }
    self.command = command;
}

/*.....................................
CLLocationManagerDelegate
..................................... */
- (void)locationManager:(CLLocationManager *)manager monitoringDidFailForRegion:(CLRegion *)region withError:(NSError *)error
{
    NSLog(@"%@", error);
}

-(void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region
{
    NSLog(@"进入范围了");
}
-(void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region
{
    NSLog(@"离开范围了");
    [self onAllBeacons];
}

-(void)locationManager:(CLLocationManager *)manager didStartMonitoringForRegion:(CLRegion *)region
{


}
-(void)locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray *)beacons inRegion:(CLBeaconRegion *)region
{
    if ([beacons count] > 0) {
        for (CLBeacon *beacon in beacons) {
            NSDictionary *beaconInputData = [self beaconInputDataByBeacon:beacon];
            NSAssert(beaconInputData, @"这里不可能没有数据");
            CLLocationAccuracy inDistance = [[beaconInputData objectForKey:@"in_distance"] doubleValue];
            CLLocationAccuracy outDistance = inDistance + 0.5F;//[[beaconInputData objectForKey:@"out_distance"] doubleValue];
            NSString *popUpMessage = [beaconInputData objectForKey:@"pop_up_message"];
            
            if (beacon.accuracy < 0) {
                NSLog(@"太远了");
                return;
            }
            
            if (inDistance >= outDistance) {
                [self.commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"In-distance can't greater than out-distance"]
                                            callbackId:self.command.callbackId];
                return ;
            }
//            NSLog(@"现在的距离是:%f", beacon.accuracy);
            if ([self getCache:beacon]) {
                if (beacon.accuracy <= inDistance) {
                    [self setCache:beacon byOn:NO];
                    
                    NSLog(@"已经进入");
                    UILocalNotification *localNotification = [[UILocalNotification alloc] init];
                    localNotification.alertBody = popUpMessage;
                    localNotification.soundName = UILocalNotificationDefaultSoundName;
                    localNotification.userInfo = @{@"beaconInputData": beaconInputData};
                    
                    [[UIApplication sharedApplication] presentLocalNotificationNow:localNotification];
                }
            } else {
                if (beacon.accuracy > outDistance) {
                    [self setCache:beacon byOn:YES];
                    NSLog(@"已经离开");
                }
            }
        }
    }
}

- (void)locationManager:(CLLocationManager *)manager didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region{
    
    NSString *stateString = nil;
    switch (state) {
        case CLRegionStateInside:
            stateString = @"inside";
            break;
        case CLRegionStateOutside:
            stateString = @"outside";
            break;
        case CLRegionStateUnknown:
            stateString = @"unknown";
            break;
    }
//    NSLog(@"State changed to %@ for region %@.", stateString, region);
    
}

/*.....................................
看看存储库里是否有，如果没有的话向上一级推送
 ..................................... */

//-(BOOL)boolNeedToTransmit:(CLBeaconRegion *)region
//{
//    NSUserDefaults *userDefault = [NSUserDefaults standardUserDefaults];
//    NSArray *array = [userDefault objectForKey:KEYARRAY];
//    NSDictionary dictionary = [self boolExitCLRegion:region];
//    
//    if (dictionary == nil)//等于空有两种情况1.default里没array 2.default里array 没这个dictionry
//    {
//        if (array == nil)
//        {
//            NSDictionary *dic = [self getRestorDataWithClRegin:region andDate:[NSDate date]];
//            NSMutableArray *arrayDefault = [NSMutableArray array];
//            [arrayDefault addObject:dic];
//            [userDefault setObject:arrayDefault forKey:KEYARRAY];
//        }
//        else
//        {
//            NSDictionary *dic = [self getRestorDataWithClRegin:region andDate:[NSDate date]];
//            NSMutableArray *arrayDefault = [NSMutableArray arrayWithArray:array];
//            [arrayDefault addObject:dic];
//            [userDefault setObject:arrayDefault forKey:KEYARRAY];
//        }
//        return YES;
//    }
//    else
//    {
//       
//            NSString *valueDate = [dictionary objectForKey:KEYTDATE];
//            NSDate *dateStore = [NSDate dateWithTimeIntervalSince1970:valueDate.doubleValue]
//            NSDate *date = [NSDate date];
//            NSTimeInterval *timeComePareNowWithOld = [date timeIntervalSinceDate:dateStore];
//           float day =timeComePareNowWithOld/(3600.0*12.0);
//
//            //可推送，大于三天
//            if (day>3.0)
//            {
//                NSDictionary *dicNew = [self getRestorDataWithClRegin:region andDate:[NSDate date]];
//                NSMutableArray *arrayMutabe = [NSMutableArray arrayWithArray:array];
//                NSInteger *interger = [array indexOfObject:dictionary];
//                [arrayMutabe replaceObjectAtIndex:interger withObject:dicNew];
//                [userDefault setObject:arrayMutabe forKey:KEYARRAY];
//                return YES;
//            }
//        return NO;
//    }
//
//
//}
//
//-(NSDictionary*)getRestorDataWithClRegin:(CLBeaconRegion *)region andDate:(NSDate*)date
//{
//    NSTimeInterval *timeInterval = [date timeIntervalSince1970];
//    NSString *strStamp = [NSString stringWithFormat:@"%d",timeInterval];
//    NSString *valueUUid = [region.proximityUUID UUIDString];
//    NSString *valueMajor = [NSString stringWithFormat:@"%i",[region.major intValue] ];
//    NSString *valueMinor = [NSString stringWithFormat:@"%i",[region.minor intValue] ];
//    NSString *valueIndenty = region.identifier;
//    
//    NSDictionary *dic = @{KEYPROXIMITYUUID: strStamp,
//                          KEYMAJOR:valueMajor,
//                          KEYMINOR:valueMinor,
//                          KEYINDENTIFY:valueIndenty}
//    return dic;
//
//}
//
////是否存在，存在就返回
//-(NSDictionary*)boolExitCLRegion:(CLBeaconRegion *)region
//{
//    NSUserDefaults *defaultUser = [NSUserDefaults standardUserDefaults];
//    NSArray *arrayBeacon = [defaultUser objectForKey:KEYARRAY];
//    if (arrayBeacon != nil) {
//        //不存在可添加
//        return nil;
//    }
//    for (int i =0;i< [arrayBeacon count];i++)
//    {
//        NSDictionary *dic = [arrayBeacon objectAtIndex:i];
//        NSString *valueUUid = [dic objectForKey:KEYPROXIMITYUUID];
//        NSString *valueMajor = [dic objectForKey:KEYMAJOR];
//        NSString *valueMinor = [dic objectForKey:KEYMINOR];
//        NSString *strDicIndentify = [dic objectForKey:KEYINDENTIFY];
//        
//        if ([[region.proximityUUID UUIDString]isEqualToString:valueUUid]&&
//            [[dic objectForKey:valueMajor]intValue]== [region.major intValue]&&
//            [[dic objectForKey:valueMinor]intValue]== [region.minor intValue]&&
//            [[dic objectForKey:KEYINDENTIFY]isEqualToString:region.identifier])
//        {
//            return dic;
//        }
//    }
//     //不存在>3天得
//    return nil;
//}

- (void)goSound:(CDVInvokedUrlCommand*)command {
    CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
                                                      messageAsString:@"Success"];
    
    [[NSNotificationCenter defaultCenter] postNotificationName:@"CDVGOTOCONTROLLER"
                                                        object:@"SOUND"];
    
    [self.commandDelegate sendPluginResult:pluginResult
                                callbackId:command.callbackId];
}

@end
